

package com.hy.activiti.service.impl;

import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hy.activiti.service.IActTaskService;
import com.hy.activiti.service.IActWorkflowFormDataService;
import com.hy.activiti.utils.ProcessDefCache;
import com.hy.common.utils.StringUtils;
import com.hy.common.utils.UserUtils;
import com.hy.common.utils.security.ShiroUtils;
import com.hy.framework.web.page.PageDomain;
import com.hy.project.activiti.domain.ActWorkflowFormData;
import com.hy.project.activiti.domain.dto.ActTaskDTO;
import com.hy.project.activiti.domain.dto.ActWorkflowFormDataDTO;
import com.hy.project.system.user.domain.User;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActTaskServiceImpl implements IActTaskService {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskRuntime taskRuntime;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IActWorkflowFormDataService actWorkflowFormDataService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private TaskService taskService;

    @Override
    public Page<ActTaskDTO> selectProcessDefinitionList(PageDomain pageDomain) {
        Page<ActTaskDTO> list = new Page<ActTaskDTO>();
        org.activiti.api.runtime.shared.query.Page<Task> pageTasks = taskRuntime.tasks(Pageable.of((pageDomain.getPageNum() - 1) * pageDomain.getPageSize(), pageDomain.getPageSize()));
        List<Task> tasks = pageTasks.getContent();
        int totalItems = pageTasks.getTotalItems();
        list.setTotal(totalItems);
        if (totalItems != 0) {
            Set<String> processInstanceIdIds = tasks.parallelStream().map(t -> t.getProcessInstanceId()).collect(Collectors.toSet());
            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIdIds).list();
            List<ActTaskDTO> actTaskDTOS = tasks.stream()
                    .map(t -> new ActTaskDTO(t, processInstanceList.parallelStream().filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get()))
                    .collect(Collectors.toList());
            list.addAll(actTaskDTOS);

        }
        return list;
    }

    /**
     * 获取已办任务
     * @param page
     * @param procDefKey 流程定义标识
     * @return
     */
    @Override
    public Page<ActTaskDTO> historicList(PageDomain pageDomain, ActTaskDTO act){
        Page<ActTaskDTO> list = new Page<ActTaskDTO>();

        String userId = ShiroUtils.getLoginName();//ObjectUtils.toString(UserUtils.getUser().getId());

        HistoricTaskInstanceQuery histTaskQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(userId).finished()
                .includeProcessVariables().orderByHistoricTaskInstanceEndTime().desc();

        // 设置查询条件
        if (StringUtils.isNotBlank(act.getDefinitionKey())){
            histTaskQuery.processDefinitionKey(act.getDefinitionKey());
        }
        if (act.getBeginDate() != null){
            histTaskQuery.taskCompletedAfter(act.getBeginDate());
        }
        if (act.getEndDate() != null){
            histTaskQuery.taskCompletedBefore(act.getEndDate());
        }

        // 查询总数
        int totalItems = (int)histTaskQuery.count();
        list.setTotal(totalItems);

        // 查询列表
        List<HistoricTaskInstance> histList = histTaskQuery.listPage(pageDomain.getFirstResult(), pageDomain.getPageSize());
        //处理分页问题
        List<ActTaskDTO> actList= Lists.newArrayList();
        for (HistoricTaskInstance histTask : histList) {
            ActTaskDTO e = new ActTaskDTO();
            e.setHistTaskIns(histTask);
            //e.setVars(histTask.getProcessVariables());
//			e.setTaskVars(histTask.getTaskLocalVariables());
//			System.out.println(histTask.getId()+"  =  "+histTask.getProcessVariables() + "  ========== " + histTask.getTaskLocalVariables());
            e.setProcDef(ProcessDefCache.get(histTask.getProcessDefinitionId()));
//			e.setProcIns(runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult());
//			e.setProcExecUrl(ActUtils.getProcExeUrl(task.getProcessDefinitionId()));
            e.setStatus("finish");
            actList.add(e);
            //page.getList().add(e);
        }
        if(totalItems  > 0)
            list.addAll(actList);
        return list;
    }

    /**
     * 获取流转历史列表
     * @param procInsId 流程实例
     * @param startAct 开始活动节点名称
     * @param endAct 结束活动节点名称
     */
    public Page<ActTaskDTO> histoicFlowList(String procInsId, String startAct, String endAct){
        Page<ActTaskDTO> actList = new Page<ActTaskDTO>();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId)
                .orderByHistoricActivityInstanceStartTime().asc().orderByHistoricActivityInstanceEndTime().asc().list();

        boolean start = false;
        Map<String, Integer> actMap = Maps.newHashMap();

        for (int i=0; i<list.size(); i++){

            HistoricActivityInstance histIns = list.get(i);

            // 过滤开始节点前的节点
            if (StringUtils.isNotBlank(startAct) && startAct.equals(histIns.getActivityId())){
                start = true;
            }
            if (StringUtils.isNotBlank(startAct) && !start){
                continue;
            }

            // 只显示开始节点和结束节点，并且执行人不为空的任务
            if (StringUtils.isNotBlank(histIns.getAssignee())
                    || "startEvent".equals(histIns.getActivityType())
                    || "endEvent".equals(histIns.getActivityType())){

                // 给节点增加一个序号
                Integer actNum = actMap.get(histIns.getActivityId());
                if (actNum == null){
                    actMap.put(histIns.getActivityId(), actMap.size());
                }

                ActTaskDTO e = new ActTaskDTO();
                e.setHistIns(histIns);
                // 获取流程发起人名称
                if ("startEvent".equals(histIns.getActivityType())){
                    List<HistoricProcessInstance> il = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).orderByProcessInstanceStartTime().asc().list();
//					List<HistoricIdentityLink> il = historyService.getHistoricIdentityLinksForProcessInstance(procInsId);
                    if (il.size() > 0){
                        if (StringUtils.isNotBlank(il.get(0).getStartUserId())){
                            User user = UserUtils.getByLoginName(il.get(0).getStartUserId());
                            if (user != null){
                                e.setAssignee(histIns.getAssignee());
                                e.setAssigneeName(user.getLoginName());
                            }
                        }
                    }
                }
                // 获取任务执行人名称
                if (StringUtils.isNotEmpty(histIns.getAssignee())){
                    User user = UserUtils.getByLoginName(histIns.getAssignee());
                    if (user != null){
                        e.setAssignee(histIns.getAssignee());
                        e.setAssigneeName(user.getLoginName());
                    }
                }
                // 获取意见评论内容
                if (StringUtils.isNotBlank(histIns.getTaskId())){
                    List<Comment> commentList = taskService.getTaskComments(histIns.getTaskId());
                    if (commentList.size()>0){
                        e.setComment(commentList.get(0).getFullMessage());
                    }
                }
                actList.add(e);
            }

            // 过滤结束节点后的节点
            if (StringUtils.isNotBlank(endAct) && endAct.equals(histIns.getActivityId())){
                boolean bl = false;
                Integer actNum = actMap.get(histIns.getActivityId());
                // 该活动节点，后续节点是否在结束节点之前，在后续节点中是否存在
                for (int j=i+1; j<list.size(); j++){
                    HistoricActivityInstance hi = list.get(j);
                    Integer actNumA = actMap.get(hi.getActivityId());
                    if ((actNumA != null && actNumA < actNum) || StringUtils.equals(hi.getActivityId(), histIns.getActivityId())){
                        bl = true;
                    }
                }
                if (!bl){
                    break;
                }
            }
        }
        return actList;
    }

    @Override
    public List<String> formDataShow(String taskID) {
        Task task = taskRuntime.task(taskID);
/*  ------------------------------------------------------------------------------
            FormProperty_0ueitp2--__!!类型--__!!名称--__!!是否参数--__!!默认值
            例子：
            FormProperty_0lovri0--__!!string--__!!姓名--__!!f--__!!同意!!__--驳回
            FormProperty_1iu6onu--__!!int--__!!年龄--__!!s

            默认值：无、字符常量、FormProperty_开头定义过的控件ID
            是否参数：f为不是参数，s是字符，t是时间(不需要int，因为这里int等价于string)
            注：类型是可以获取到的，但是为了统一配置原则，都配置到
            */

        //注意!!!!!!!!:表单Key必须要任务编号一模一样，因为参数需要任务key，但是无法获取，只能获取表单key“task.getFormKey()”当做任务key
        UserTask userTask = (UserTask) repositoryService.getBpmnModel(task.getProcessDefinitionId())
                .getFlowElement(task.getFormKey());

        if (userTask == null) {
            return null;
        }
        List<FormProperty> formProperties = userTask.getFormProperties();
        List<String> collect = formProperties.stream().map(fp -> fp.getId()).collect(Collectors.toList());

        return collect;
    }

    @Override
    public int formDataSave(String taskID, List<ActWorkflowFormDataDTO> awfs) throws ParseException {
        Task task = taskRuntime.task(taskID);
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();

        Boolean hasVariables = false;//没有任何参数
        HashMap<String, Object> variables = new HashMap<String, Object>();
        //前端传来的字符串，拆分成每个控件
        List<ActWorkflowFormData> acwfds = new ArrayList<>();
        for (ActWorkflowFormDataDTO awf : awfs) {
            ActWorkflowFormData actWorkflowFormData = new ActWorkflowFormData(processInstance.getBusinessKey(),awf, task);
            acwfds.add(actWorkflowFormData);
            //构建参数集合
            if(!"f".equals(awf.getControlIsParam())) {
                    variables.put(awf.getControlId(), awf.getControlValue());
                    hasVariables = true;
            }
        }//for结束
        if (task.getAssignee() == null) {
            taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
        }
        if (hasVariables) {
            //带参数完成任务
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID)
                    .withVariables(variables)
                    .build());
        } else {
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID)
                    .build());
        }


        //写入数据库
        return actWorkflowFormDataService.insertActWorkflowFormDatas(acwfds);
    }
}
